﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Runtime.Serialization;

namespace AMSService.model
{
    [DataContract (IsReference=true)]//(Namespace="AMSService.model")]
    public class User : DBConnector
    {
        private int _id = 0;
        private string _name;
        private string _pw;
        private List<Asset> _assets;

        // Stored procedure names
        private const string _spdeluser = "DeleteUserById";
        private const string _spgetuser = "GetUserById";
        private const string _spinsuser = "InsertUser";
        private const string _spisvalid = "IsValidUser";
        private const string _spupduser = "UpdateUser";
        private const string _spuserexists = "GetUserByUserName";

        // Stored procedure argument names
        private const string _prmid = "@id";
        private const string _prmusernm = "@uname";
        private const string _prmuserpw = "@upass";

        // Table field names
        private const string _fldid = "pkid";
        private const string _fldusernm = "uname";
        private const string _flduserpw = "upassword";

        public User()
        {
            _id = 0;
            _pw = "";
            _assets = new List<Asset>();
        }

        public User(int ID)
        {
            if (ID > 0) 
            {
                _id = ID;
                LoadData();
            }
            _assets = new List<Asset>();
        }

        public User(string UserName, string Password)
        {
            _name = UserName;
            _pw = Password;
            ValidateUser();
            _assets = new List<Asset>();
        }

        [DataMember]
        public int ID
        {
            get { return _id; }
            set { _id = value;  }
        }

        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember]
        public string Password
        {
            get { return _pw; }
            set { _pw = value; }
        }

        public bool IsValid
        {
            get { return _id > 0; }
        }

        [DataMember]
        public List<Asset> Assets
        {
            get { return _assets; }
            private set { }
        }

        // Deletes this user record from the database.
        public bool Delete()
        {
            List<SqlParameter> paramlist = new List<SqlParameter>();
            SqlParameter pid = new SqlParameter(_prmid, _id);
            paramlist.Add(pid);

            return SendWriteRequest(_spdeluser, paramlist) > 0;
        }

        // Get all assets associated with this user.
        public void LoadAssets()
        {
            DataTable dt = SendReadRequest(Asset.SpSelect,
                new SqlParameter[] { new SqlParameter(Asset.SpPrmId, _id),
                                     new SqlParameter(Asset.SpPrmArg, Asset._spargs.userid) });

            if (_assets == null)
                _assets = new List<Asset>();
            else
                _assets.Clear();

            foreach (DataRow dr in dt.Rows)
            {
                Asset a = new Asset(this, dr);
                a.LoadPurchaseData();
                a.LoadScheduleData();
                a.LoadServiceData();
                a.LoadWarrantyData();
                _assets.Add(a);
            }
        }

        // Populates this object from the database.
        private bool LoadData()
        {
            List<SqlParameter> paramlist = new List<SqlParameter>();
            SqlParameter pid = new SqlParameter(_prmid, _id);
            DataTable dt;

            paramlist.Add(pid);

            if (_id > 0)
            {
                dt = SendReadRequest(_spgetuser, paramlist);
                if (dt.Rows.Count > 0)
                    return LoadData(dt.Rows[0]);
            }
            return false;
        }

        // Hydrates this object from the specified data row.
        private bool LoadData(DataRow Row)
        {
            try
            {
                _name = Convert.ToString(Row[_fldusernm]);
                _pw = Convert.ToString(Row[_flduserpw]);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        // Indicates whether this objects user name is already represented in the database.
        public bool UserExists()
        {
            List<SqlParameter> paramlist = new List<SqlParameter>();
            SqlParameter puname = new SqlParameter(_prmusernm, _name);
            DataTable dt;

            paramlist.Add(puname);

            dt = SendReadRequest(_spuserexists, paramlist);
            return dt.Rows.Count > 0;
        }

        // Saves this user to the database.  If this object does not have a
        // primary key value, this method creates a new record.  If it does have
        // a primary key value, this method updates the existing record.
        public bool Save()
        {
            List<SqlParameter> paramlist = new List<SqlParameter>();
            SqlParameter pid = new SqlParameter(_prmid, _id);
            SqlParameter puname = new SqlParameter(_prmusernm, _name);
            SqlParameter ppass = new SqlParameter(_prmuserpw, _pw);

            paramlist.Add(puname);
            paramlist.Add(ppass);

            // If this is an update request (the id already exists)
            if (_id > 0)
            {
                paramlist.Add(pid);
                return SendWriteRequest(_spupduser, paramlist) > 0;
            }
            else
            {
                _id = SendWriteRequest(_spinsuser, paramlist);
                return _id > 0;
            }
        }

        private void ValidateUser()
        {
            try
            {
                List<SqlParameter> paramlist = new List<SqlParameter>();
                SqlParameter pname = new SqlParameter(_prmusernm, _name);
                SqlParameter ppw = new SqlParameter(_prmuserpw, _pw);
                paramlist.Add(pname);
                paramlist.Add(ppw);
                DataTable dt = SendReadRequest(_spisvalid, paramlist);
                if (dt.Rows.Count > 0)
                    _id = Int32.Parse(dt.Rows[0][_fldid].ToString());
                else
                    _id = 0;
            }
            catch (Exception ex)
            {
                _id = 0;
            }
        }
    }
}